//Внутренняя библиотека.
#include "vidcodec.h"


//===========================================================================//
//=Заголовок: VidCodec::VidCodec() - public
//=Параметры:
//=Описание: Конструктор.
//===========================================================================//
VidCodec::VidCodec(QObject *parent) : QThread(parent)
{
vCodec = NULL; vCodecCtx = NULL;

outBuf = NULL; outBufSize = 0;

//Инициализировать FFMPEG.
av_register_all();
}


//===========================================================================//
//=Заголовок: bool VidCodec::setIndex() - public
//=Параметры:
//=Описание: Функция установки текущего видеокодека по индексу.
//===========================================================================//
bool VidCodec::setIndex(int index)
{
CodecID id = getIDFromIndex(index);
if(id == CODEC_ID_NONE) return false;

AVCodec *codec = avcodec_find_encoder(id);
if(!codec) return false;

vCodec = codec;

return true;
}


//===========================================================================//
//=Заголовок: int VidCodec::getIndex() - public
//=Параметры:
//=Описание: Функция возврата индекса текущего видеокодека.
//===========================================================================//
int VidCodec::getIndex()
{
if(!vCodec) return -1;
return getIndexFromID(vCodec->id);
}


//===========================================================================//
//=Заголовок: void VidCodec::encode() - public
//=Параметры:
//=Описание: Функция кодирования видео.
//===========================================================================//
void VidCodec::encode()
{
/*if(!vCodec) return;
if(!vidframe) return;

//if(vCodecCtx) {avcodec_close(vCodecCtx); av_free(vCodecCtx);}
if(!vCodecCtx)
	{
	vCodecCtx = avcodec_alloc_context();
	vCodecCtx->codec_type = CODEC_TYPE_VIDEO;
	vCodecCtx->codec_id = vCodec->id;

	//Дополнительно для FFV1.
	if(vCodec->id == CODEC_ID_FFV1) vCodecCtx->strict_std_compliance = -2;

	vCodecCtx->bit_rate = 2500000; //bps;
	vCodecCtx->width = vidframe->getWidth();
	vCodecCtx->height = vidframe->getHeight();

	vCodecCtx->time_base.num = 1;
	vCodecCtx->time_base.den = 25; //fps;

	//if(vbr) vCodecCtx->flags |= CODEC_FLAG_QSCALE;

	vCodecCtx->gop_size = 10;

	vCodecCtx->pix_fmt = vidframe->getFFMPEGPixFormat();

	if(avcodec_open(vCodecCtx, vCodec) < 0) return;

	outBufSize = avpicture_get_size(vCodecCtx->pix_fmt, vCodecCtx->width, vCodecCtx->height);
	outBuf = (uint8_t *)malloc(outBufSize);
}

vidFrame = vidframe;

start(QThread::HighestPriority);*/
}


//===========================================================================//
//=Заголовок: void VidCodec::run() - protected
//=Параметры:
//=Описание: Функция активации нити.
//===========================================================================//
void VidCodec::run()
{
/*if(!vidFrame) return;
if(!outBuf) return;

AVFrame *srcpic = avcodec_alloc_frame();
if(!srcpic) return;
avpicture_fill((AVPicture*)srcpic, vidFrame->getData(), vCodecCtx->pix_fmt, vCodecCtx->width, vCodecCtx->height);

AVFrame *dstpic = avcodec_alloc_frame();
if(!dstpic) return;
avpicture_fill((AVPicture*)dstpic, outBuf, vCodecCtx->pix_fmt, vCodecCtx->width, vCodecCtx->height);

int out_size = avcodec_encode_video(vCodecCtx, outBuf, outBufSize, srcpic);
if(out_size != 0)
	{
	AVPacket pkt;
	av_init_packet(&pkt);
	pkt.stream_index = videoStream->index;
	if(codecCtx->coded_frame->pts != (unsigned)(0x8000000000000000LL))
		pkt.pts = av_rescale_q(vCodecCtx->coded_frame->pts, vCodecCtx->time_base, videoStream->time_base);
	if(codecCtx->coded_frame->key_frame)
		pkt.flags |= PKT_FLAG_KEY;

	pkt.data = outBuf;
	pkt.size = out_size;
	av_interleaved_write_frame(fmtCtx, &pkt);
}

av_free(srcpic);
av_free(dstpic);*/
}


//===========================================================================//
//=Заголовок: static void VidCodec::enumSupportedCodecs() - public
//=Параметры:
//=Описание: Функция возврата списка наименований видеокодеков.
//===========================================================================//
void VidCodec::enumSupportedCodecs(PixelFormat pixfmt, QHash<int, QVariant> *nameshash)
{
AVCodec *codec = NULL;
while((codec = av_codec_next(codec)))
	{
	//Интересуют только видеокодеки.
	if(!codec->encode || codec->type != CODEC_TYPE_VIDEO) continue;

	//Получить список поддерживаемых видеокодеком видеоформатов.
	const PixelFormat *supported_pix_fmts = codec->pix_fmts;
	if(!supported_pix_fmts) continue;

	//Найти в полученном списке указанный видеоформат.
	bool is_supported = false;
	while(*supported_pix_fmts != -1)
		{
		if(pixfmt == *supported_pix_fmts) {is_supported = true; break;}
		supported_pix_fmts++;
	}
	if(!is_supported) continue;

	//Проверить, что имеется хотя бы один формат видеофайла,
	//поддерживающего текущий видеокодек.
	bool found_output_fmt = false;
	AVOutputFormat *outputfmt = NULL;
	while((outputfmt = av_oformat_next(outputfmt)))
		{
		if(!av_codec_get_tag(outputfmt->codec_tag, codec->id)) continue;
		found_output_fmt = true; break;
	}
	if(!found_output_fmt) continue;

	//Получить индекс видеокодека.
	int index = getIndexFromID(codec->id);
	if(index == -1) continue;

	//Получить наименование видеокодека.
	char *name = new char[strlen((char*)codec->long_name) + 1];
	strcpy(name, (char*)codec->long_name);
	nameshash->insert(index, QString(name));
	delete[] name;
}
}


//===========================================================================//
//=Заголовок: static void VidCodec::enumSupportedFormats() - public
//=Параметры:
//=Описание: Функция возврата списка наименований форматов видеофайлов.
//===========================================================================//
void VidCodec::enumSupportedFormats(int vcodec_index, QHash<int, QVariant> *nameshash)
{
CodecID id = getIDFromIndex(vcodec_index);
if(id == CODEC_ID_NONE) return;

AVCodec *codec = avcodec_find_encoder(id);
if(!codec) return;

QList<AVOutputFormat *> ofmtslist;

AVOutputFormat *outputfmt = NULL;
while((outputfmt = av_oformat_next(outputfmt)))
	{
	if(!av_codec_get_tag(outputfmt->codec_tag, codec->id)) continue;

	bool exists_fmt = false;
	foreach(AVOutputFormat *ofmt, ofmtslist)
		{
		if(strcmp(ofmt->name, outputfmt->name) == 0)
			{exists_fmt = true; break;}
	}
	if(!exists_fmt) ofmtslist.append(outputfmt);
}

for(int i = 0; i < ofmtslist.size(); ++i)
	{
	char *name = new char[strlen((char*)ofmtslist.at(i)->long_name) + 1];
	strcpy(name, (char*)ofmtslist.at(i)->long_name);
	QString long_name = QString(name);
	delete[] name;

	name = new char[strlen((char*)ofmtslist.at(i)->name) + 1];
	strcpy(name, (char*)ofmtslist.at(i)->name);
	QString short_name = QString(name);
	delete[] name;

	nameshash->insert(i, long_name + " (" + short_name + ")");
}
}


//===========================================================================//
//=Заголовок: static int VidCodec::getIndexFromID() - public
//=Параметры:
//=Описание: Функция возврата индекса видеокодека от его идентификатора.
//===========================================================================//
int VidCodec::getIndexFromID(CodecID id)
{
switch(id)
	{
	case CODEC_ID_MPEG1VIDEO:      return 0;
	case CODEC_ID_MPEG2VIDEO:      return 1;
	case CODEC_ID_MPEG2VIDEO_XVMC: return 2;
	case CODEC_ID_H261:            return 3;
	case CODEC_ID_H263:            return 4;
	case CODEC_ID_RV10:            return 5;
	case CODEC_ID_RV20:            return 6;
	case CODEC_ID_MJPEG:           return 7;
	case CODEC_ID_MJPEGB:          return 8;
	case CODEC_ID_LJPEG:           return 9;
	case CODEC_ID_SP5X:            return 10;
	case CODEC_ID_JPEGLS:          return 11;
	case CODEC_ID_MPEG4:           return 12;
	case CODEC_ID_RAWVIDEO:        return 13;
	case CODEC_ID_MSMPEG4V1:       return 14;
	case CODEC_ID_MSMPEG4V2:       return 15;
	case CODEC_ID_MSMPEG4V3:       return 16;
	case CODEC_ID_WMV1:            return 17;
	case CODEC_ID_WMV2:            return 18;
	case CODEC_ID_H263P:           return 19;
	case CODEC_ID_H263I:           return 20;
	case CODEC_ID_FLV1:            return 21;
	case CODEC_ID_SVQ1:            return 22;
	case CODEC_ID_SVQ3:            return 23;
	case CODEC_ID_DVVIDEO:         return 24;
	case CODEC_ID_HUFFYUV:         return 25;
	case CODEC_ID_CYUV:            return 26;
	case CODEC_ID_H264:            return 27;
	case CODEC_ID_INDEO3:          return 28;
	case CODEC_ID_VP3:             return 29;
	case CODEC_ID_THEORA:          return 30;
	case CODEC_ID_ASV1:            return 31;
	case CODEC_ID_ASV2:            return 32;
	case CODEC_ID_FFV1:            return 33;
	case CODEC_ID_4XM:             return 34;
	case CODEC_ID_VCR1:            return 35;
	case CODEC_ID_CLJR:            return 36;
	case CODEC_ID_MDEC:            return 37;
	case CODEC_ID_ROQ:             return 38;
	case CODEC_ID_INTERPLAY_VIDEO: return 39;
	case CODEC_ID_XAN_WC3:         return 40;
	case CODEC_ID_XAN_WC4:         return 41;
	case CODEC_ID_RPZA:            return 42;
	case CODEC_ID_CINEPAK:         return 43;
	case CODEC_ID_WS_VQA:          return 44;
	case CODEC_ID_MSRLE:           return 45;
	case CODEC_ID_MSVIDEO1:        return 46;
	case CODEC_ID_IDCIN:           return 47;
	case CODEC_ID_8BPS:            return 48;
	case CODEC_ID_SMC:             return 49;
	case CODEC_ID_FLIC:            return 50;
	case CODEC_ID_TRUEMOTION1:     return 51;
	case CODEC_ID_VMDVIDEO:        return 52;
	case CODEC_ID_MSZH:            return 53;
	case CODEC_ID_ZLIB:            return 54;
	case CODEC_ID_QTRLE:           return 55;
	case CODEC_ID_SNOW:            return 56;
	case CODEC_ID_TSCC:            return 57;
	case CODEC_ID_ULTI:            return 58;
	case CODEC_ID_QDRAW:           return 59;
	case CODEC_ID_VIXL:            return 60;
	case CODEC_ID_QPEG:            return 61;
	case CODEC_ID_XVID:            return 62;
	case CODEC_ID_PNG:             return 63;
	case CODEC_ID_PPM:             return 64;
	case CODEC_ID_PBM:             return 65;
	case CODEC_ID_PGM:             return 66;
	case CODEC_ID_PGMYUV:          return 67;
	case CODEC_ID_PAM:             return 68;
	case CODEC_ID_FFVHUFF:         return 69;
	case CODEC_ID_RV30:            return 70;
	case CODEC_ID_RV40:            return 71;
	case CODEC_ID_VC1:             return 72;
	case CODEC_ID_WMV3:            return 73;
	case CODEC_ID_LOCO:            return 74;
	case CODEC_ID_WNV1:            return 75;
	case CODEC_ID_AASC:            return 76;
	case CODEC_ID_INDEO2:          return 77;
	case CODEC_ID_FRAPS:           return 78;
	case CODEC_ID_TRUEMOTION2:     return 79;
	case CODEC_ID_BMP:             return 80;
	case CODEC_ID_CSCD:            return 81;
	case CODEC_ID_MMVIDEO:         return 82;
	case CODEC_ID_ZMBV:            return 83;
	case CODEC_ID_AVS:             return 84;
	case CODEC_ID_SMACKVIDEO:      return 85;
	case CODEC_ID_NUV:             return 86;
	case CODEC_ID_KMVC:            return 87;
	case CODEC_ID_FLASHSV:         return 88;
	case CODEC_ID_CAVS:            return 89;
	case CODEC_ID_JPEG2000:        return 90;
	case CODEC_ID_VMNC:            return 91;
	case CODEC_ID_VP5:             return 92;
	case CODEC_ID_VP6:             return 93;
	case CODEC_ID_VP6F:            return 94;
	case CODEC_ID_TARGA:           return 95;
	case CODEC_ID_DSICINVIDEO:     return 96;
	case CODEC_ID_TIERTEXSEQVIDEO: return 97;
	case CODEC_ID_TIFF:            return 98;
	case CODEC_ID_GIF:             return 99;
	case CODEC_ID_FFH264:          return 100;
	case CODEC_ID_DXA:             return 101;
	case CODEC_ID_DNXHD:           return 102;
	case CODEC_ID_THP:             return 103;
	case CODEC_ID_SGI:             return 104;
	case CODEC_ID_C93:             return 105;
	case CODEC_ID_BETHSOFTVID:     return 106;
	case CODEC_ID_PTX:             return 107;
	case CODEC_ID_TXD:             return 108;
	case CODEC_ID_VP6A:            return 109;
	case CODEC_ID_AMV:             return 110;
	case CODEC_ID_VB:              return 111;
	case CODEC_ID_PCX:             return 112;
	case CODEC_ID_SUNRAST:         return 113;
	case CODEC_ID_INDEO4:          return 114;
	case CODEC_ID_INDEO5:          return 115;
	case CODEC_ID_MIMIC:           return 116;
	case CODEC_ID_RL2:             return 117;
	case CODEC_ID_8SVX_EXP:        return 118;
	case CODEC_ID_8SVX_FIB:        return 119;
	case CODEC_ID_ESCAPE124:       return 120;
	case CODEC_ID_DIRAC:           return 121;
	case CODEC_ID_BFI:             return 122;
	case CODEC_ID_CMV:             return 123;
	case CODEC_ID_MOTIONPIXELS:    return 124;
	case CODEC_ID_TGV:             return 125;
	case CODEC_ID_TGQ:             return 126;
	case CODEC_ID_TQI:             return 127;
	default: break;
}

return -1;
}


//===========================================================================//
//=Заголовок: static CodecID VidCodec::getIDFromIndex() - public
//=Параметры:
//=Описание: Функция возврата идентификатора видеокодека от его индекса.
//===========================================================================//
CodecID VidCodec::getIDFromIndex(int index)
{
switch(index)
	{
	case 0:   return CODEC_ID_MPEG1VIDEO;
	case 1:   return CODEC_ID_MPEG2VIDEO;
	case 2:   return CODEC_ID_MPEG2VIDEO_XVMC;
	case 3:   return CODEC_ID_H261;
	case 4:   return CODEC_ID_H263;
	case 5:   return CODEC_ID_RV10;
	case 6:   return CODEC_ID_RV20;
	case 7:   return CODEC_ID_MJPEG;
	case 8:   return CODEC_ID_MJPEGB;
	case 9:   return CODEC_ID_LJPEG;
	case 10:  return CODEC_ID_SP5X;
	case 11:  return CODEC_ID_JPEGLS;
	case 12:  return CODEC_ID_MPEG4;
	case 13:  return CODEC_ID_RAWVIDEO;
	case 14:  return CODEC_ID_MSMPEG4V1;
	case 15:  return CODEC_ID_MSMPEG4V2;
	case 16:  return CODEC_ID_MSMPEG4V3;
	case 17:  return CODEC_ID_WMV1;
	case 18:  return CODEC_ID_WMV2;
	case 19:  return CODEC_ID_H263P;
	case 20:  return CODEC_ID_H263I;
	case 21:  return CODEC_ID_FLV1;
	case 22:  return CODEC_ID_SVQ1;
	case 23:  return CODEC_ID_SVQ3;
	case 24:  return CODEC_ID_DVVIDEO;
	case 25:  return CODEC_ID_HUFFYUV;
	case 26:  return CODEC_ID_CYUV;
	case 27:  return CODEC_ID_H264;
	case 28:  return CODEC_ID_INDEO3;
	case 29:  return CODEC_ID_VP3;
	case 30:  return CODEC_ID_THEORA;
	case 31:  return CODEC_ID_ASV1;
	case 32:  return CODEC_ID_ASV2;
	case 33:  return CODEC_ID_FFV1;
	case 34:  return CODEC_ID_4XM;
	case 35:  return CODEC_ID_VCR1;
	case 36:  return CODEC_ID_CLJR;
	case 37:  return CODEC_ID_MDEC;
	case 38:  return CODEC_ID_ROQ;
	case 39:  return CODEC_ID_INTERPLAY_VIDEO;
	case 40:  return CODEC_ID_XAN_WC3;
	case 41:  return CODEC_ID_XAN_WC4;
	case 42:  return CODEC_ID_RPZA;
	case 43:  return CODEC_ID_CINEPAK;
	case 44:  return CODEC_ID_WS_VQA;
	case 45:  return CODEC_ID_MSRLE;
	case 46:  return CODEC_ID_MSVIDEO1;
	case 47:  return CODEC_ID_IDCIN;
	case 48:  return CODEC_ID_8BPS;
	case 49:  return CODEC_ID_SMC;
	case 50:  return CODEC_ID_FLIC;
	case 51:  return CODEC_ID_TRUEMOTION1;
	case 52:  return CODEC_ID_VMDVIDEO;
	case 53:  return CODEC_ID_MSZH;
	case 54:  return CODEC_ID_ZLIB;
	case 55:  return CODEC_ID_QTRLE;
	case 56:  return CODEC_ID_SNOW;
	case 57:  return CODEC_ID_TSCC;
	case 58:  return CODEC_ID_ULTI;
	case 59:  return CODEC_ID_QDRAW;
	case 60:  return CODEC_ID_VIXL;
	case 61:  return CODEC_ID_QPEG;
	case 62:  return CODEC_ID_XVID;
	case 63:  return CODEC_ID_PNG;
	case 64:  return CODEC_ID_PPM;
	case 65:  return CODEC_ID_PBM;
	case 66:  return CODEC_ID_PGM;
	case 67:  return CODEC_ID_PGMYUV;
	case 68:  return CODEC_ID_PAM;
	case 69:  return CODEC_ID_FFVHUFF;
	case 70:  return CODEC_ID_RV30;
	case 71:  return CODEC_ID_RV40;
	case 72:  return CODEC_ID_VC1;
	case 73:  return CODEC_ID_WMV3;
	case 74:  return CODEC_ID_LOCO;
	case 75:  return CODEC_ID_WNV1;
	case 76:  return CODEC_ID_AASC;
	case 77:  return CODEC_ID_INDEO2;
	case 78:  return CODEC_ID_FRAPS;
	case 79:  return CODEC_ID_TRUEMOTION2;
	case 80:  return CODEC_ID_BMP;
	case 81:  return CODEC_ID_CSCD;
	case 82:  return CODEC_ID_MMVIDEO;
	case 83:  return CODEC_ID_ZMBV;
	case 84:  return CODEC_ID_AVS;
	case 85:  return CODEC_ID_SMACKVIDEO;
	case 86:  return CODEC_ID_NUV;
	case 87:  return CODEC_ID_KMVC;
	case 88:  return CODEC_ID_FLASHSV;
	case 89:  return CODEC_ID_CAVS;
	case 90:  return CODEC_ID_JPEG2000;
	case 91:  return CODEC_ID_VMNC;
	case 92:  return CODEC_ID_VP5;
	case 93:  return CODEC_ID_VP6;
	case 94:  return CODEC_ID_VP6F;
	case 95:  return CODEC_ID_TARGA;
	case 96:  return CODEC_ID_DSICINVIDEO;
	case 97:  return CODEC_ID_TIERTEXSEQVIDEO;
	case 98:  return CODEC_ID_TIFF;
	case 99:  return CODEC_ID_GIF;
	case 100: return CODEC_ID_FFH264;
	case 101: return CODEC_ID_DXA;
	case 102: return CODEC_ID_DNXHD;
	case 103: return CODEC_ID_THP;
	case 104: return CODEC_ID_SGI;
	case 105: return CODEC_ID_C93;
	case 106: return CODEC_ID_BETHSOFTVID;
	case 107: return CODEC_ID_PTX;
	case 108: return CODEC_ID_TXD;
	case 109: return CODEC_ID_VP6A;
	case 110: return CODEC_ID_AMV;
	case 111: return CODEC_ID_VB;
	case 112: return CODEC_ID_PCX;
	case 113: return CODEC_ID_SUNRAST;
	case 114: return CODEC_ID_INDEO4;
	case 115: return CODEC_ID_INDEO5;
	case 116: return CODEC_ID_MIMIC;
	case 117: return CODEC_ID_RL2;
	case 118: return CODEC_ID_8SVX_EXP;
	case 119: return CODEC_ID_8SVX_FIB;
	case 120: return CODEC_ID_ESCAPE124;
	case 121: return CODEC_ID_DIRAC;
	case 122: return CODEC_ID_BFI;
	case 123: return CODEC_ID_CMV;
	case 124: return CODEC_ID_MOTIONPIXELS;
	case 125: return CODEC_ID_TGV;
	case 126: return CODEC_ID_TGQ;
	case 127: return CODEC_ID_TQI;
	default:  break;
}

return CODEC_ID_NONE;
}
